# -*- coding: utf-8 -*-
"""
管理员预约管理视图

为管理员提供全面的预约监管功能：
- 查看所有预约记录
- 处理预约冲突
- 预约统计分析
- 管理员强制操作
"""

from flask import Blueprint, render_template, request, jsonify, flash, redirect, url_for
from flask_login import login_required, current_user
from sqlalchemy import func, and_, or_, text
from datetime import datetime, timedelta, date
import json

from app.models.reservation import Reservation
from app.models.user import User
from app.models.table import Table
from app.models.campus import Campus
from app.controllers.reservation_controller import ReservationController
from app.forms.reservation_forms import AdminEditReservationForm
from app.decorators import admin_required
from app import db

# 创建蓝图
admin_reservations_bp = Blueprint('admin_reservations', __name__)


@admin_reservations_bp.route('/')
@admin_reservations_bp.route('/list')
@login_required
@admin_required
def list_reservations():
    """
    预约列表页面

    支持多维度筛选：
    - 状态筛选
    - 时间范围筛选
    - 校区筛选
    - 教练筛选
    - 学员筛选
    """
    # 获取筛选参数
    status = request.args.get('status', '')
    campus_id = request.args.get('campus_id', type=int)
    coach_id = request.args.get('coach_id', type=int)
    student_id = request.args.get('student_id', type=int)
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    search = request.args.get('search', '').strip()
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 10, type=int)

    # 构建查询
    query = Reservation.query

    # 权限控制：校区管理员只能查看自己校区的预约
    if current_user.role == 'campus_admin':
        query = query.filter(Reservation.campus_id == current_user.campus_id)
        # 校区管理员不允许切换校区，强制使用自己的校区
        campus_id = current_user.campus_id
    elif current_user.role == 'super_admin':
        # 超级管理员可以查看所有校区，但如果指定了校区则按校区筛选
        if campus_id:
            query = query.filter(Reservation.campus_id == campus_id)

    # 状态筛选
    if status:
        query = query.filter(Reservation.status == status)

    # 教练筛选
    if coach_id:
        query = query.filter(Reservation.coach_id == coach_id)

    # 学员筛选
    if student_id:
        query = query.filter(Reservation.student_id == student_id)

    # 时间范围筛选
    if start_date:
        try:
            start_date_obj = datetime.strptime(start_date, '%Y-%m-%d').date()
            query = query.filter(Reservation.reservation_date >= start_date_obj)
        except ValueError:
            pass

    if end_date:
        try:
            end_date_obj = datetime.strptime(end_date, '%Y-%m-%d').date()
            query = query.filter(Reservation.reservation_date <= end_date_obj)
        except ValueError:
            pass

    # 搜索
    if search:
        query = query.join(User, Reservation.student_id == User.id).filter(
            or_(
                User.real_name.contains(search),
                User.phone.contains(search)
            )
        )

    # 排序
    query = query.order_by(Reservation.created_at.desc())

    # 分页
    reservations = query.paginate(
        page=page, per_page=per_page, error_out=False
    )

    # 获取筛选选项数据
    if current_user.role == 'campus_admin':
        # 校区管理员只能看到自己的校区和校区内的教练
        campuses = Campus.query.filter_by(id=current_user.campus_id).all()
        coaches = User.query.filter(
            User.role == 'coach',
            User.campus_id == current_user.campus_id,
            User.status == 'active'
        ).all()
    else:
        # 超级管理员可以看到所有校区和教练
        campuses = Campus.query.all()
        coaches = User.query.filter(
            User.role == 'coach',
            User.status == 'active'
        ).all()

    # 统计数据也要根据权限进行限制
    if current_user.role == 'campus_admin':
        # 校区管理员只看自己校区的统计
        base_query = Reservation.query.filter(Reservation.campus_id == current_user.campus_id)
        total_count = base_query.count()
        today_count = base_query.filter(
            Reservation.reservation_date == date.today()
        ).count()
        pending_count = base_query.filter_by(status='pending').count()
    else:
        # 超级管理员看全局统计
        total_count = Reservation.query.count()
        today_count = Reservation.query.filter(
            Reservation.reservation_date == date.today()
        ).count()
        pending_count = Reservation.query.filter_by(status='pending').count()

    conflict_count = _get_conflict_count()

    return render_template(
        'admin_reservations/list.html',
        reservations=reservations,
        campuses=campuses,
        coaches=coaches,
        current_filters={
            'status': status,
            'campus_id': campus_id,
            'coach_id': coach_id,
            'student_id': student_id,
            'start_date': start_date,
            'end_date': end_date,
            'search': search
        },
        stats={
            'total_count': total_count,
            'today_count': today_count,
            'pending_count': pending_count,
            'total_reservations': total_count  # 保持模板兼容性
        }
    )


@admin_reservations_bp.route('/detail/<int:reservation_id>')
@login_required
@admin_required
def detail(reservation_id):
    """
    预约详情页面

    显示预约的完整信息和操作历史
    允许管理员进行强制操作
    """
    reservation = Reservation.query.get_or_404(reservation_id)

    # 检查是否有时间冲突 - 冲突检测功能已移除
    conflicts = []

    # 获取相关的其他预约
    related_reservations = Reservation.query.filter(
        and_(
            Reservation.id != reservation_id,
            or_(
                Reservation.student_id == reservation.student_id,
                Reservation.coach_id == reservation.coach_id
            ),
            Reservation.reservation_date.between(
                reservation.reservation_date - timedelta(days=7),
                reservation.reservation_date + timedelta(days=7)
            )
        )
    ).order_by(Reservation.reservation_date, Reservation.start_time).all()

    # 计算一些统计信息
    student_stats = _get_student_stats(reservation.student_id)
    coach_stats = _get_coach_stats(reservation.coach_id)

    return render_template(
        'admin_reservations/detail.html',
        reservation=reservation,
        conflicts=conflicts,
        related_reservations=related_reservations,
        student_stats=student_stats,
        coach_stats=coach_stats
    )


@admin_reservations_bp.route('/edit/<int:reservation_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit(reservation_id):
    """
    编辑预约页面

    允许管理员编辑预约的所有信息：
    - 教练、球台、时间、价格、状态、备注等
    """
    reservation = Reservation.query.get_or_404(reservation_id)

    # 获取校区ID（直接从预约记录获取）
    campus_id = reservation.campus_id

    # 权限检查：校区管理员只能编辑自己校区的预约
    if current_user.role == 'campus_admin' and current_user.campus_id != campus_id:
        flash('您没有权限编辑其他校区的预约', 'error')
        return redirect(url_for('admin_reservations.list_reservations'))

    form = AdminEditReservationForm(
        reservation=reservation,
        campus_id=campus_id
    )

    if form.validate_on_submit():
        try:
            # 保存原始数据用于比较
            original_data = {
                'coach_id': reservation.coach_id,
                'table_id': reservation.table_id,
                'reservation_date': reservation.reservation_date,
                'start_time': reservation.start_time,
                'end_time': reservation.end_time,
                'status': reservation.status,
                'price': reservation.price
            }

            # 更新预约信息
            reservation.coach_id = int(form.coach_id.data)
            reservation.table_id = int(form.table_id.data)
            reservation.reservation_date = form.reservation_date.data
            reservation.start_time = form.start_time.data
            reservation.end_time = form.end_time.data
            reservation.status = form.status.data
            reservation.price = form.price.data
            # reservation.notes = form.notes.data  # notes字段在数据库中不存在

            # 计算并更新时长
            reservation.duration_minutes = form.calculate_duration_minutes()

            # 更新修改时间
            reservation.updated_at = datetime.now()

            # 如果状态改为取消，记录取消信息
            if (original_data['status'] != 'cancelled' and
                form.status.data == 'cancelled'):
                reservation.cancelled_at = datetime.now()
                reservation.cancelled_by = current_user.id
                if not reservation.cancel_reason:
                    reservation.cancel_reason = '管理员编辑时设为取消'

            db.session.commit()

            # 冲突检测功能已移除
            flash('预约信息已成功更新', 'success')

            return redirect(url_for('admin_reservations.detail', reservation_id=reservation.id))

        except ValueError as e:
            db.session.rollback()
            flash(f'数据格式错误：{str(e)}', 'error')

        except Exception as e:
            db.session.rollback()
            flash(f'保存失败：{str(e)}', 'error')

    # GET请求或表单验证失败时显示编辑页面
    return render_template(
        'admin_reservations/edit.html',
        form=form,
        reservation=reservation
    )


@admin_reservations_bp.route('/statistics')
@login_required
@admin_required
def statistics():
    """
    预约统计分析页面

    提供多维度的统计分析：
    - 预约趋势分析
    - 教练工作量分析
    - 学员活跃度分析
    - 球台使用率分析
    - 收入统计分析
    """
    # 获取时间范围参数
    period = request.args.get('period', 'month')  # week, month, quarter, year
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    campus_id = request.args.get('campus_id', type=int)

    # 设置默认时间范围
    if not start_date or not end_date:
        end_date_obj = date.today()
        if period == 'week':
            start_date_obj = end_date_obj - timedelta(days=7)
        elif period == 'month':
            start_date_obj = end_date_obj - timedelta(days=30)
        elif period == 'quarter':
            start_date_obj = end_date_obj - timedelta(days=90)
        else:  # year
            start_date_obj = end_date_obj - timedelta(days=365)

        start_date = start_date_obj.strftime('%Y-%m-%d')
        end_date = end_date_obj.strftime('%Y-%m-%d')

    # 基础查询
    base_query = Reservation.query.filter(
        Reservation.reservation_date.between(start_date, end_date)
    )

    if campus_id:
        base_query = base_query.join(Table).filter(Table.campus_id == campus_id)

    # 1. 总体统计
    overall_stats = _get_overall_statistics(base_query)

    # 2. 预约趋势数据
    trend_data = _get_reservation_trend(base_query, period, start_date, end_date)

    # 3. 教练工作量分析
    coach_stats = _get_coach_workload_stats(base_query)

    # 4. 学员活跃度分析
    student_stats = _get_student_activity_stats(base_query)

    # 5. 球台使用率分析
    table_stats = _get_table_usage_stats(base_query)

    # 6. 收入统计
    revenue_stats = _get_revenue_stats(base_query)

    # 7. 状态分布
    status_distribution = _get_status_distribution(base_query)

    # 获取校区列表
    campuses = Campus.query.all()

    return render_template(
        'admin_reservations/statistics.html',
        overall_stats=overall_stats,
        trend_data=trend_data,
        coach_stats=coach_stats,
        student_stats=student_stats,
        table_stats=table_stats,
        revenue_stats=revenue_stats,
        status_distribution=status_distribution,
        campuses=campuses,
        current_period=period,
        current_campus_id=campus_id,
        start_date=start_date,
        end_date=end_date
    )




# API 端点
@admin_reservations_bp.route('/api/force_confirm/<int:reservation_id>', methods=['POST'])
@login_required
@admin_required
def api_force_confirm(reservation_id):
    """强制确认预约"""
    try:
        reservation = Reservation.query.get_or_404(reservation_id)

        if reservation.status != 'pending':
            return jsonify({
                'success': False,
                'message': '只能确认待处理状态的预约'
            })

        reservation.status = 'confirmed'

        db.session.commit()

        return jsonify({
            'success': True,
            'message': '预约已强制确认'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'操作失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/force_cancel/<int:reservation_id>', methods=['POST'])
@login_required
@admin_required
def api_force_cancel(reservation_id):
    """强制取消预约"""
    try:
        reservation = Reservation.query.get_or_404(reservation_id)
        reason = request.json.get('reason', '管理员强制取消')

        if reservation.status in ['cancelled', 'completed']:
            return jsonify({
                'success': False,
                'message': '该预约已经是最终状态，无法取消'
            })

        reservation.status = 'cancelled'
        reservation.cancelled_at = datetime.now()
        reservation.cancel_reason = reason
        reservation.cancelled_by = current_user.id

        db.session.commit()

        return jsonify({
            'success': True,
            'message': '预约已强制取消'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'操作失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/resolve_conflict', methods=['POST'])
@login_required
@admin_required
def api_resolve_conflict():
    """解决预约冲突"""
    try:
        conflict_id = request.json.get('conflict_id')
        resolution = request.json.get('resolution')  # 'cancel_first', 'cancel_second', 'reschedule'

        # 这里应该根据具体的冲突类型和解决方案来处理
        # 为了简化，这里只是一个示例

        return jsonify({
            'success': True,
            'message': '冲突已解决'
        })

    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'解决冲突失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/duplicate/<int:reservation_id>', methods=['POST'])
@login_required
@admin_required
def api_duplicate_reservation(reservation_id):
    """复制预约"""
    try:
        original = Reservation.query.get_or_404(reservation_id)

        # 创建新的预约对象，复制原预约的信息
        new_reservation = Reservation(
            student_id=original.student_id,
            coach_id=original.coach_id,
            table_id=original.table_id,
            reservation_date=original.reservation_date + timedelta(days=1),  # 默认复制到第二天
            start_time=original.start_time,
            end_time=original.end_time,
            duration_minutes=original.duration_minutes,
            price=original.price,
            status='pending',  # 新预约默认为待处理状态
            created_at=datetime.now(),
            updated_at=datetime.now()
        )

        db.session.add(new_reservation)
        db.session.commit()

        return jsonify({
            'success': True,
            'message': f'预约已复制，新预约ID：{new_reservation.id}',
            'new_reservation_id': new_reservation.id
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'复制失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/delete/<int:reservation_id>', methods=['POST'])
@login_required
@admin_required
def api_delete_reservation(reservation_id):
    """删除单个预约"""
    try:
        reservation = Reservation.query.get_or_404(reservation_id)

        db.session.delete(reservation)
        db.session.commit()

        return jsonify({
            'success': True,
            'message': '预约已删除'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'删除失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/bulk_action', methods=['POST'])
@login_required
@admin_required
def api_bulk_action():
    """批量操作预约"""
    try:
        reservation_ids = request.json.get('reservation_ids', [])
        action = request.json.get('action')  # confirm, cancel, delete
        reason = request.json.get('reason', '')

        if not reservation_ids:
            return jsonify({
                'success': False,
                'message': '请选择要操作的预约'
            })

        reservations = Reservation.query.filter(
            Reservation.id.in_(reservation_ids)
        ).all()

        if not reservations:
            return jsonify({
                'success': False,
                'message': '未找到指定的预约'
            })

        success_count = 0

        for reservation in reservations:
            try:
                if action == 'confirm' and reservation.status == 'pending':
                    reservation.status = 'confirmed'
                    success_count += 1

                elif action == 'cancel' and reservation.status not in ['cancelled', 'completed']:
                    reservation.status = 'cancelled'
                    reservation.cancelled_at = datetime.now()
                    reservation.cancel_reason = reason or '管理员批量取消'
                    reservation.cancelled_by = current_user.id
                    success_count += 1

                elif action == 'delete':
                    db.session.delete(reservation)
                    success_count += 1

            except Exception:
                continue

        db.session.commit()

        return jsonify({
            'success': True,
            'message': f'批量操作完成，成功处理 {success_count} 个预约'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'批量操作失败：{str(e)}'
        })


@admin_reservations_bp.route('/api/export')
@login_required
@admin_required
def api_export():
    """导出预约数据"""
    try:
        # 获取导出参数
        export_type = request.args.get('type', 'csv')  # csv, excel
        filters = request.args.to_dict()

        # 这里应该实现具体的导出逻辑
        # 为了简化，返回一个示例响应

        return jsonify({
            'success': True,
            'download_url': '/path/to/exported/file.csv',
            'message': '导出成功'
        })

    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'导出失败：{str(e)}'
        })


# 辅助函数
def _get_conflict_count():
    """获取冲突数量"""
    # 冲突检测功能已移除
    return 0


def _get_student_stats(student_id):
    """获取学员统计信息"""
    total_reservations = Reservation.query.filter_by(student_id=student_id).count()
    completed_reservations = Reservation.query.filter_by(
        student_id=student_id, status='completed'
    ).count()
    cancelled_reservations = Reservation.query.filter_by(
        student_id=student_id, status='cancelled'
    ).count()

    return {
        'total_reservations': total_reservations,
        'completed_reservations': completed_reservations,
        'cancelled_reservations': cancelled_reservations,
        'completion_rate': (completed_reservations / total_reservations * 100) if total_reservations > 0 else 0
    }


def _get_coach_stats(coach_id):
    """获取教练统计信息"""
    total_reservations = Reservation.query.filter_by(coach_id=coach_id).count()
    completed_reservations = Reservation.query.filter_by(
        coach_id=coach_id, status='completed'
    ).count()

    return {
        'total_reservations': total_reservations,
        'completed_reservations': completed_reservations,
        'completion_rate': (completed_reservations / total_reservations * 100) if total_reservations > 0 else 0
    }


def _get_overall_statistics(base_query):
    """获取总体统计数据"""
    total_reservations = base_query.count()

    status_counts = db.session.query(
        Reservation.status,
        func.count(Reservation.id)
    ).filter(
        Reservation.id.in_(base_query.with_entities(Reservation.id))
    ).group_by(Reservation.status).all()

    status_dict = dict(status_counts)

    # 计算收入
    total_revenue = db.session.query(
        func.sum(Reservation.price)
    ).filter(
        Reservation.id.in_(base_query.with_entities(Reservation.id)),
        Reservation.status == 'completed'
    ).scalar() or 0

    return {
        'total_reservations': total_reservations,
        'pending_count': status_dict.get('pending', 0),
        'confirmed_count': status_dict.get('confirmed', 0),
        'completed_count': status_dict.get('completed', 0),
        'cancelled_count': status_dict.get('cancelled', 0),
        'total_revenue': float(total_revenue),
        'average_price': float(total_revenue / status_dict.get('completed', 1))
    }


def _get_reservation_trend(base_query, period, start_date, end_date):
    """获取预约趋势数据"""
    # 这里应该根据不同的时间周期返回趋势数据
    # 为了简化，返回示例数据
    return {
        'labels': ['第1周', '第2周', '第3周', '第4周'],
        'data': [25, 35, 28, 42]
    }


def _get_coach_workload_stats(base_query):
    """获取教练工作量统计"""
    coach_stats = db.session.query(
        User.real_name,
        func.count(Reservation.id).label('total_reservations'),
        func.sum(Reservation.duration_minutes).label('total_minutes')
    ).join(
        Reservation, User.id == Reservation.coach_id
    ).filter(
        Reservation.id.in_(base_query.with_entities(Reservation.id))
    ).group_by(User.id, User.real_name).all()

    return [
        {
            'coach_name': stat.real_name,
            'total_reservations': stat.total_reservations,
            'total_hours': (stat.total_minutes or 0) / 60
        }
        for stat in coach_stats
    ]


def _get_student_activity_stats(base_query):
    """获取学员活跃度统计"""
    # 实现学员活跃度统计逻辑
    return []


def _get_table_usage_stats(base_query):
    """获取球台使用率统计"""
    # 实现球台使用率统计逻辑
    return []


def _get_revenue_stats(base_query):
    """获取收入统计"""
    # 实现收入统计逻辑
    return {}


def _get_status_distribution(base_query):
    """获取状态分布"""
    status_counts = db.session.query(
        Reservation.status,
        func.count(Reservation.id)
    ).filter(
        Reservation.id.in_(base_query.with_entities(Reservation.id))
    ).group_by(Reservation.status).all()

    return dict(status_counts)


